home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / fchart / fcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  46.3 KB  |  1,824 lines

  1. /* Fchart - fcmd.c */
  2. /*
  3.  * Gnuplot code
  4.  * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  5.  *
  6.  * Permission to use, copy, and distribute this software and its
  7.  * documentation for any purpose with or without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and
  9.  * that both that copyright notice and this permission notice appear
  10.  * in supporting documentation.
  11.  *
  12.  * Permission to modify the software is granted, but not the right to
  13.  * distribute the modified code.  Modifications are to be distributed
  14.  * as patches to released version.
  15.  *
  16.  * This software  is provided "as is" without express or implied warranty.
  17.  *
  18.  *
  19.  * AUTHORS
  20.  *
  21.  *   Original Software:
  22.  *     Thomas Williams,  Colin Kelley.
  23.  *
  24.  *   Gnuplot 2.0 additions:
  25.  *       Russell Lang, Dave Kotz, John Campbell.
  26.  *
  27.  *   Fchart changes and additions:
  28.  *       Piotr Filip Sawicki
  29.  *
  30.  * send your comments or suggestions to fs@uwasa.fi
  31.  *
  32.  */
  33. #include <stdio.h>
  34. #include <math.h>
  35. #include <ctype.h>
  36.  
  37. #ifdef MSDOS
  38. #include <process.h>
  39.  
  40. #ifdef __ZTC__
  41. #define P_WAIT 0
  42. #include <time.h>       /* usleep() */
  43. #else
  44.  
  45. #ifdef __TURBOC__
  46. #include <dos.h>        /* sleep() */
  47.  
  48. #else   /* must be MSC */
  49. #include <time.h>       /* kludge to provide sleep() */
  50. void sleep();           /* defined later */
  51. #endif /* TURBOC */
  52. #endif /* ZTC */
  53.  
  54. #endif /* MSDOS */
  55.  
  56. #include "plot.h"
  57. #include "fchart.h"
  58. #include "help.h"
  59.  
  60. #ifndef STDOUT
  61. #define STDOUT 1
  62. #endif
  63.  
  64. #ifndef HELPFILE
  65. #define HELPFILE "fchart.gih" /* changed by makefile */
  66. #endif
  67.  
  68. /* global defs for default values */
  69. #define DEF_T_FORMAT "%g"    /* make it as narrow as possible */
  70. #define EXPL_RAD 0.3        /* ratio of explosion of a slice */
  71. #define MAXBARWIDTH 0.2        /* default maximal allowable width of bar */
  72. #define INTERBAR 0.2        /* interbar space in terms of real bar width */
  73. #define INTERGROUP 0.5        /* space between groups of bars */
  74. #define OTHER "other"        /* name for combined slice */
  75.  
  76. /*
  77.  * global variables to hold status of 'set' options
  78.  *
  79.  */
  80.  
  81. BOOLEAN            autoscale    = TRUE,
  82.                 auto_label    = FALSE,
  83.                 p_clockwise    = TRUE,
  84.                 b_clockwise = TRUE,
  85.                 draw_border = TRUE;
  86.  
  87. enum DRAW_STYLE data_style    = ABARS;
  88. enum GRAV_DIR    gravity        = SOUTH,
  89.                 explode        = DEFAULT;
  90. enum INP_STYLE    inp_style    = PRIVATE;
  91. enum FONT_STYLE    vect_font    = F_WHENN;
  92. BOOLEAN            log_y        = FALSE;
  93. FILE*            outfile;
  94. char            outstr[MAX_LINE_LEN+1] = "STDOUT";
  95. int                samples        = SAMPLES;
  96. int                term        = 0;            /* unknown term is 0 */
  97. int                xmin        = -1,
  98.                 xmax        = -1;
  99. double            base        = 0.0;
  100. double            loff        = 0.0,
  101.                 roff        = 0.0,
  102.                 toff        = 0.0,
  103.                 boff        = 0.0;
  104. double            b_wid        = MAXBARWIDTH,
  105.                 b_int        = INTERBAR,
  106.                 b_spc        = INTERGROUP;
  107. double            radexp        = EXPL_RAD;        /* explosion power */
  108. double            zero        = ZERO;            /* zero threshold, not 0! */
  109. int                HLitem        = HL_NON;        /* no highliting by default */
  110. struct pair        data_place    = { -1, -1 },    /* not defined yet */
  111.                 label_plac    = { -1, -1 };    /* not defined yet */
  112. float            xsize        = 1.0,
  113.                 ysize        = 1.0;
  114. double            treshold    = 0.0;
  115. char            thrname[MAX_LINE_LEN+1] = OTHER;
  116. char             tic_form[MAX_LINE_LEN+1]    = DEF_T_FORMAT;
  117. int                strunc        = -1;
  118.  
  119. struct dfile data_head = { NULL, 0.0, 0.0, 0, 0, HL_NON, FALSE, NULL, NULL } ;
  120.  
  121. BOOLEAN screen_ok;
  122. BOOLEAN term_init;
  123. /* BOOLEAN undefined; */  /* probably not even used */
  124.  
  125. /*
  126.  * instead of <strings.h>
  127.  */
  128.  
  129. char *gets(),*getenv(),*sprintf();    /* for lint only */
  130. char *strcpy(),*strncpy(),*strcat();
  131.  
  132. extern double real();
  133. extern void set_label(), set_nolabel(), set_arrow(), set_noarrow();
  134. extern void show_labels(), show_arrow();
  135.  
  136. extern struct termentry term_tbl[];
  137.  
  138. struct lexical_unit token[MAX_TOKENS];
  139. char input_line[MAX_LINE_LEN+1] = "";
  140. int num_tokens, c_token;
  141.  
  142. static char replot_line[MAX_LINE_LEN+1];
  143. static int plot_token;                    /* start of 'plot' command */
  144.  
  145. extern void squash_spaces(), lower_case();
  146.  
  147. com_line()
  148. {
  149.     read_line(PROMPT);
  150.  
  151.     screen_ok = interactive;        /* see 'Gnuplot' why */
  152.  
  153.     do_line();
  154. }
  155.  
  156.  
  157. do_line()      /* also used in load_file */
  158. {
  159.     if (is_system(input_line[0])) {
  160.         do_system();
  161.         fputs("!\n",stderr);
  162.         return;
  163.     }
  164.     num_tokens = scanner(input_line);
  165.     c_token = 0;
  166.     while(c_token < num_tokens) {
  167.         command();
  168.         if (c_token < num_tokens)    /* something after command */
  169.             if (equals(c_token,";"))
  170.                 c_token++;
  171.             else
  172.                     int_error("';' expected",c_token);
  173.     }
  174. }
  175.  
  176. command()
  177. {
  178.     static char sv_file[MAX_LINE_LEN+1];
  179.             /* string holding name of save or load file */
  180.  
  181.     if (equals(c_token,"help") || equals(c_token,"?")) {
  182.         c_token++;
  183.         do_help();
  184.     }
  185.     else if (almost_equals(c_token,"test")) {
  186.         c_token++;
  187.         term_test();
  188.     }
  189.     else if (almost_equals(c_token,"pa$use")) {
  190.         int stime=1, text=0;
  191.         char buf[MAX_LINE_LEN+1];
  192.  
  193.         c_token++;
  194.         if (equals(c_token,"-")) stime=-1, c_token++;
  195.         stime *= (int)real(c_token);
  196.         c_token++;
  197.         if (!(END_OF_COMMAND)) {
  198.             if (!isstring(c_token))
  199.                 int_error("expecting string",c_token);
  200.             else {
  201.                 quote_str(buf,c_token);
  202.                 fprintf (stderr, "%s",buf);
  203.                 text = 1;
  204.             }
  205.         }
  206.         if (stime < 0) fgets (buf,MAX_LINE_LEN,stdin);  /* Hold until CR hit */
  207. #ifdef __ZTC__
  208.         if (stime > 0) usleep((unsigned long) stime);
  209. #else        
  210.         if (stime > 0) sleep((unsigned) stime);
  211. #endif
  212.         if (text != 0 && stime >= 0) fprintf (stderr,"\n");
  213.         c_token++;
  214.         screen_ok = FALSE;
  215.     }
  216.     else if (almost_equals(c_token,"p$lot") ||
  217.              almost_equals(c_token,"d$raw")) {
  218.         plot_token = c_token++;
  219.         plotrequest(FALSE);
  220.     }
  221.     else if (almost_equals(c_token,"tp$lot") ||
  222.              almost_equals(c_token,"td$raw") ||
  223.              almost_equals(c_token,"xp$lot") ||        /* for backward compatibility */
  224.              almost_equals(c_token,"xd$raw") ||        /* for backward compatibility */
  225.              almost_equals(c_token,"trans_plot") ||
  226.              almost_equals(c_token,"trans_draw")) {
  227.         plot_token = c_token++;
  228.         plotrequest(TRUE);
  229.     }
  230.     else if (almost_equals(c_token,"rep$lot") ||
  231.              almost_equals(c_token,"red$raw")) {
  232.         c_token++;
  233.         if (replot_line[0] == '\0') 
  234.             int_error("no previous plot",c_token);
  235.         if (!END_OF_COMMAND) {
  236.             char str[MAX_LINE_LEN+1];
  237.             capture(str,c_token,num_tokens-1);
  238.             if ((strlen(str)+strlen(input_line)) <= MAX_LINE_LEN-1) {
  239.                 (void) strcat(replot_line,",");
  240.                 (void) strcat(replot_line,str);
  241.             }
  242.             else
  243.                 int_error("plot line too long with replot arguments",c_token);
  244.         }
  245.         (void) strcpy(input_line,replot_line);
  246.         screen_ok = FALSE;
  247.         num_tokens = scanner(input_line);
  248.         c_token = 1;                    /* skip the 'plot' part */
  249.         plotrequest(almost_equals(0,"td$raw") ||
  250.                     almost_equals(0,"tp$lot") ||
  251.                     almost_equals(0,"xd$raw") ||
  252.                     almost_equals(0,"xp$lot") ||
  253.                     almost_equals(0,"tr$ans_plot") ||
  254.                     almost_equals(0,"tr$ans_draw"));  /* fetch plot type */
  255.     }
  256.     else if (almost_equals(c_token,"se$t"))
  257.         set_stuff();
  258.     else if (almost_equals(c_token,"sh$ow"))
  259.         show_stuff();
  260.     else if (almost_equals(c_token,"sa$ve")) {
  261.         c_token++;
  262.         if (END_OF_COMMAND || !isstring(c_token))
  263.             int_error("name of file expected", c_token);
  264.         quote_str(sv_file,c_token);
  265.         save_sets(fopen(sv_file,"w"));
  266.         /* c_token updated in save_sets */
  267.     }
  268.     else if (almost_equals(c_token,"cl$ear")) {
  269.         if (!term_init) {
  270.             (*term_tbl[term].init)();
  271.             term_init = TRUE;
  272.         }
  273.         (*term_tbl[term].graphics)();
  274.         (*term_tbl[term].text)();
  275.         (void) fflush(outfile);
  276.         screen_ok = FALSE;
  277.         c_token++;
  278.     }
  279.     else if (almost_equals(c_token,"she$ll")) {
  280.         do_shell();
  281.         screen_ok = FALSE;
  282.         c_token++;
  283.     }
  284.     else if (almost_equals(c_token,"l$oad") ||
  285.              almost_equals(c_token,"r$ead")) {
  286.         if (!isstring(++c_token))
  287.             int_error("expecting filename",c_token);
  288.         else {
  289.             quote_str(sv_file,c_token);
  290.             load_file(fopen(sv_file,"r"));    
  291.         /* input_line[] and token[] now destroyed! */
  292.             c_token = num_tokens = 0;
  293.         }
  294.     }
  295.     else if (almost_equals(c_token,"ex$it") ||
  296.             almost_equals(c_token,"q$uit")) {
  297.         done(IO_SUCCESS);
  298.     }
  299.     else if (!equals(c_token,";")) {        /* null statement */
  300.         int_error("Invalid command. Try:\n\
  301. '?/help', 'test', 'pause', '[t]draw/[t]plot',\n\
  302. 'replot/redraw', 'set', 'show', 'save', 'shell',\n\
  303. 'load/read', 'exit/quit'",c_token);
  304.     }
  305. }
  306.  
  307.  
  308. enum DRAW_STYLE
  309. get_style()
  310. {
  311. register enum DRAW_STYLE ps;
  312.  
  313.     c_token++;
  314.     if (almost_equals(c_token,"a$djacent_bars"))
  315.         ps = ABARS;
  316.     else if (almost_equals(c_token,"l$ayer_bars"))
  317.         ps = LAYB;
  318.     else if (almost_equals(c_token,"s$tacked_bars"))
  319.         ps = SBAR;
  320.     else if (almost_equals(c_token,"p$iechart"))
  321.         ps = PIECHART;
  322.     else
  323.         int_error("expecting 'adjacent_bars', 'stacked_bars', 'layer_bars' or 'piechart'",c_token);
  324.     c_token++;
  325.     return(ps);
  326. }
  327.  
  328. enum GRAV_DIR
  329. get_gravity()
  330. {
  331.     c_token++;
  332.     if (END_OF_COMMAND) return(DEFAULT);
  333.     else if (almost_equals(c_token,"b$ottom") || almost_equals(c_token,"s$outh")) {
  334.         c_token++;
  335.         return(SOUTH);
  336.     }
  337.     else if (almost_equals(c_token,"t$op") || almost_equals(c_token,"n$orth")) {
  338.         c_token++;
  339.         return(NORTH);
  340.     }
  341.     else if (almost_equals(c_token,"l$eft") || almost_equals(c_token,"w$est")) {
  342.         c_token++;
  343.         return(WEST);
  344.     }
  345.     else if (almost_equals(c_token,"r$ight") || almost_equals(c_token,"e$ast")) {
  346.         c_token++;
  347.         return(EAST);
  348.     }
  349.     else
  350.         int_error("expecting direction: 'left/west', 'right/east',\n'bottom/south' or 'top/north'",c_token);
  351.     /*NOTREACHED*/
  352. }
  353.  
  354. enum INP_STYLE
  355. get_input()
  356. {
  357.     if (END_OF_COMMAND) return(PRIVATE);
  358.     else if (almost_equals(c_token,"g$nuplot")) {
  359.         c_token++;
  360.         return(GNUPLOT);
  361.     }
  362.     else if (almost_equals(c_token,"p$rivate")) {
  363.         c_token++;
  364.         return(PRIVATE);
  365.     }
  366.     else if (almost_equals(c_token,"c$ustomized")) {
  367.         c_token++;
  368.         return(CUSTOMD);
  369.     }
  370.     else
  371.         int_error("expected 'gnuplot', 'private' or 'customized'",c_token);
  372.     /*NOTREACHED*/
  373. }
  374.  
  375. set_stuff()
  376. {
  377.     static char testfile[MAX_LINE_LEN+1];
  378.  
  379.     if (almost_equals(++c_token,"b$ar")) {
  380.         set_bar_stuff();
  381.     }
  382.     else if (almost_equals(c_token,"fr$ame")) {
  383.         draw_border = TRUE;
  384.         c_token++;
  385.     }
  386.     else if (almost_equals(c_token,"nof$rame")) {
  387.         draw_border = FALSE;
  388.         c_token++;
  389.     }
  390.     else if (almost_equals(c_token,"for$mat")) {
  391.         c_token++;
  392.         if (END_OF_COMMAND)
  393.             (void) strcpy(tic_form, DEF_T_FORMAT);
  394.         else if (!isstring(c_token))
  395.             int_error("enquoted format expected", c_token);
  396.         else 
  397.             quote_str(tic_form, c_token++);
  398.     }
  399.     else if (almost_equals(c_token,"fon$t")) {
  400.         c_token++;
  401.         if (END_OF_COMMAND)
  402.             vect_font = F_ALWYS;
  403.         else {
  404.             if (almost_equals(c_token,"n$ever")) 
  405.                 vect_font = F_NEVER;
  406.             else if (almost_equals(c_token,"w$hen_needed"))
  407.                 vect_font = F_WHENN;
  408.             else if (almost_equals(c_token,"r$otated"))
  409.                 vect_font = F_ROTAT;
  410.             else if (almost_equals(c_token,"a$lways"))
  411.                 vect_font = F_ALWYS;
  412.             else
  413.                 int_error("'never', 'when_needed', 'rotated', or 'always' expected",c_token);
  414.             c_token++;
  415.         }
  416.     }    
  417.     else if (almost_equals(c_token,"au$tolabeling")) {
  418.         auto_label = TRUE;
  419.         c_token++;
  420.     }
  421.     else if (almost_equals(c_token,"noau$tolabeling")) {
  422.         auto_label = FALSE;
  423.         c_token++;
  424.     }
  425.     else if (almost_equals(c_token,"ar$row")) {
  426.         c_token++;
  427.         set_arrow(TRUE);
  428.     }
  429.     else if (almost_equals(c_token,"noar$row")) {
  430.         c_token++;
  431.         set_noarrow();
  432.     }
  433.     else if (almost_equals(c_token,"c$ustomized")) {
  434.         c_token++;
  435.         if (END_OF_COMMAND) {
  436.             data_place.from = -1;    /* not defined */
  437.             label_plac.from = -1;    /* thus no label */
  438.         }
  439.         else {
  440.             if (!equals(c_token,"["))
  441.                 int_error("expecting '['",c_token);
  442.             c_token++;
  443.             load_range(&data_place.from,&data_place.upto);
  444.             if (!equals(c_token,"]"))
  445.                 int_error("expecting ']'",c_token);
  446.             c_token++;
  447.             if (END_OF_COMMAND)
  448.                 label_plac.from = -1;    /* no label */
  449.             else {
  450.                 if (equals(c_token,",")) c_token++;        /* optional ',' */
  451.                 if (!equals(c_token,"["))
  452.                     int_error("expecting '['",c_token);
  453.                 c_token++;
  454.                 load_range(&label_plac.from,&label_plac.upto);
  455.                 if (!equals(c_token,"]"))
  456.                     int_error("expected ']'",c_token);
  457.                 c_token++;
  458.             }
  459.             if (!check_ranges(&data_place,&label_plac)) {    /* overlapping ranges ? */
  460.                 data_place.from = label_plac.from = -1;
  461.                 int_error("value and label places are overlapping or are empty",NO_CARET);
  462.             }
  463.         }
  464.     }
  465.     else if (almost_equals(c_token,"h$ighlight")) {
  466.         c_token++;
  467.         HLitem = get_HL();
  468.     }
  469.     else if (almost_equals(c_token,"i$nput")) {
  470.         c_token++;
  471.         inp_style = get_input();
  472.     }
  473.     else if (almost_equals(c_token,"lo$gscale")) {
  474.         c_token++;
  475.         log_y = TRUE;
  476.     }
  477.     else if (almost_equals(c_token,"nolo$gscale")) {
  478.         log_y = FALSE;
  479.         c_token++;
  480.     }
  481.     else if (almost_equals(c_token,"la$bel")) {
  482.         c_token++;
  483.         set_label();
  484.     }
  485.     else if (almost_equals(c_token,"nola$bel")) {
  486.         c_token++;
  487.         set_nolabel();
  488.     }
  489.     else if (almost_equals(c_token,"li$ne")) {
  490.         c_token++;
  491.         set_arrow(FALSE);
  492.     }
  493.     else if (almost_equals(c_token,"noli$ne")) {
  494.         c_token++;
  495.         set_noarrow();
  496.     }    
  497.     else if (almost_equals(c_token,"of$fsets")) {
  498.         c_token++;
  499.         if (END_OF_COMMAND) {
  500.             loff = roff = toff = boff = 0.0;  /* Reset offsets */
  501.         }
  502.         else {
  503.             load_offsets (&loff,&roff,&toff,&boff);
  504.             if ((loff>1.0 ? loff/100.0 : loff) + (roff>1.0 ? roff/100.0 : roff) >= 1.0 ||
  505.                 (boff>1.0 ? boff/100.0 : boff) + (toff>1.0 ? toff/100.0 : toff) >= 1.0) {
  506.                 loff = roff = toff = boff = 0.0;  /* Reset offsets for the future */
  507.                 int_error("null picture size within given offsets",NO_CARET);
  508.             }
  509.         }
  510.     }
  511.     else if (almost_equals(c_token,"o$utput")) {
  512.         register FILE *f;
  513.  
  514.         c_token++;
  515.         if (END_OF_COMMAND) {    /* no file specified */
  516.              UP_redirect (4);
  517.             if (outfile != stdout) /* Never close stdout */
  518.                 (void) fclose(outfile);
  519.             outfile = stdout; /* Avoid the dup... */
  520.             term_init = FALSE;
  521.             (void) strcpy(outstr,"STDOUT");
  522.         } else if (!isstring(c_token))
  523.             int_error("expecting filename",c_token);
  524.         else {
  525.             quote_str(testfile,c_token);
  526.             if (!(f = fopen(testfile,"w"))) {
  527.               os_error("cannot open file; output not changed",c_token);
  528.             }
  529.             if (outfile != stdout) /* Never close stdout */
  530.                 (void) fclose(outfile);
  531.             outfile = f;
  532.             term_init = FALSE;
  533.             outstr[0] = '\'';
  534.             (void) strcat(strcpy(outstr+1,testfile),"'");
  535.              UP_redirect (1);
  536.         }
  537.         c_token++;
  538.     }
  539.     else if (almost_equals(c_token,"p$ie")) {
  540.         set_pie_stuff();
  541.     }
  542.     else if (almost_equals(c_token,"si$ze")) {
  543.         c_token++;
  544.         if (END_OF_COMMAND) {
  545.             xsize = 1.0;
  546.             ysize = 1.0;
  547.         }
  548.         else {
  549.             xsize = (float)real(c_token);
  550.             c_token++;
  551.             if (!equals(c_token,","))
  552.                 int_error("',' expected",c_token);
  553.             c_token++;
  554.             if (END_OF_COMMAND)
  555.                 int_error("value for ysize expected",c_token);
  556.             ysize = (float)real(c_token);
  557.             c_token++;
  558.         }
  559.     }        
  560.     else if (almost_equals(c_token,"st$yle")) {
  561.         data_style = get_style();
  562.     }
  563.     else if (almost_equals(c_token,"te$rminal")) {
  564.         c_token++;
  565.         if (END_OF_COMMAND) {
  566.             list_terms();
  567.             screen_ok = FALSE;
  568.         }
  569.         else {
  570.             if (term && term_init) {
  571.                 (*term_tbl[term].reset)();
  572.                 (void) fflush(outfile);
  573.             }            
  574.             term = set_term(c_token);
  575.             c_token++;
  576.         }
  577.     }
  578.     else if (almost_equals(c_token,"ti$tle")) {
  579.         c_token++;
  580.         if (END_OF_COMMAND) {
  581.             if (data_head.fname)
  582.                 free(data_head.fname);
  583.             data_head.fname = NULL;
  584.         }
  585.         else if (isstring(c_token)) {
  586.             m_quote_capture(&(data_head.fname), c_token, c_token);
  587.             c_token++;
  588.         }
  589.         else
  590.             int_error("title within quotes expected", c_token);
  591.     }
  592.     else if (almost_equals(c_token,"tr$uncate")) {
  593.         c_token++;
  594.         if (END_OF_COMMAND)
  595.             strunc = 0;
  596.         else {
  597.             strunc = real(c_token);
  598.             c_token++;
  599.         }
  600.     }
  601.     else if (almost_equals(c_token,"not$runcate")) {
  602.         c_token++;
  603.         strunc = -1;
  604.     }
  605.     else if (almost_equals(c_token,"r$ange")) {
  606.         c_token++;
  607.         if (END_OF_COMMAND) xmin=-1;
  608.         else {
  609.             if (!equals(c_token,"["))
  610.                 int_error("expecting '['",c_token);
  611.             c_token++;
  612.             load_range(&xmin,&xmax);
  613.             if (!equals(c_token,"]"))
  614.                 int_error("expecting ']'",c_token);
  615.             c_token++;
  616.             if (xmax != -1 && xmax < xmin) {
  617.                 xmin = -1;  /* whole */
  618.                 int_error("given range is empty",NO_CARET);
  619.             }
  620.         }
  621.     }
  622.     else if (almost_equals(c_token,"z$ero") ||
  623.              almost_equals(c_token,"eps$ilon")) {
  624.         int sign=1;
  625.         c_token++;
  626.         if (equals(c_token,"-")) sign=-1, c_token++;
  627.         zero = sign*real(c_token);
  628.         c_token++;
  629.     }
  630.     else
  631.         int_error(
  632.     "valid set options:  'bar', '[no]logscale',\n\
  633. 'customized', 'format', 'highlight', 'offsets'\n\
  634. 'output', 'pie', 'style', '[no]autolabeling',\n\
  635. 'terminal', 'title', 'range', 'zero/epsilon',\n\
  636. '[no]frame', 'font', '[no]truncate', '[no]label',\n\
  637. '[no]arrow', '[no]line'",
  638.     c_token);
  639. }
  640.  
  641. set_bar_stuff()
  642. {
  643.     if (almost_equals(++c_token,"a$utoscale")) {
  644.         autoscale = TRUE;
  645.         c_token++;
  646.     }
  647.     else if (almost_equals(c_token,"noa$utoscale")) {
  648.         autoscale = FALSE;
  649.         c_token++;
  650.     }
  651.     else if (almost_equals(c_token,"b$ase")) {
  652.         int sign = 1;
  653.         c_token++;
  654.         if (END_OF_COMMAND) base = 0.0;
  655.         else {
  656.             if (equals(c_token,"-")) c_token++, sign=-1;
  657.             base = sign*real(c_token);
  658.             c_token++;
  659.         }
  660.     }
  661.     else if (almost_equals(c_token,"cl$ockwise")) {
  662.         b_clockwise = TRUE;
  663.         c_token++;
  664.     }
  665.     else if (almost_equals(c_token,"co$unter_clockwise")) {
  666.         b_clockwise = FALSE;
  667.         c_token++;
  668.     }
  669.     else if (almost_equals(c_token,"g$ravitation")) {
  670.         gravity = get_gravity();
  671.         if (gravity==DEFAULT) gravity = SOUTH;
  672.     }
  673.     else if (almost_equals(c_token,"w$idth")) {
  674.         c_token++;
  675.         if (END_OF_COMMAND) {
  676.             b_wid = MAXBARWIDTH;
  677.             b_int = INTERBAR;
  678.             b_spc = INTERGROUP;
  679.         }
  680.         else
  681.             load_offsets(&b_wid, &b_int, &b_spc, (double *) NULL);
  682.     }
  683.     else
  684.         int_error("valid options:  '[no]autoscale', 'base',\n\
  685. '[counter_]clockwise', 'gravitation', 'width'",c_token);
  686. }
  687.  
  688. set_pie_stuff()
  689. {
  690.     if (almost_equals(++c_token,"ex$plode")) {
  691.         explode = get_gravity();
  692.     }
  693.     else if (almost_equals(c_token,"cl$ockwise")) {
  694.         p_clockwise = TRUE;
  695.         c_token++;
  696.     }
  697.     else if (almost_equals(c_token,"co$unter_clockwise")) {
  698.         p_clockwise = FALSE;
  699.         c_token++;
  700.     }
  701.     else if (almost_equals(c_token,"r$adius")) {
  702.         c_token++;
  703.         if (END_OF_COMMAND)
  704.             radexp = EXPL_RAD;
  705.         else {
  706.             radexp = real(c_token);
  707.             c_token++;
  708.         }
  709.     }
  710.     else if (almost_equals(c_token,"s$amples")) {
  711.         register int tsamp;
  712.  
  713.         c_token++;
  714.         tsamp = (int)real(c_token);
  715.         if (tsamp < 1)
  716.             int_error("sampling rate must be > 0; sampling unchanged",
  717.                 c_token);
  718.         else samples = tsamp;
  719.         c_token++;
  720.     }
  721.     else if (almost_equals(c_token,"t$hreshold")) {
  722.         c_token++;
  723.         if (END_OF_COMMAND) {
  724.             treshold = 0.0;
  725.             strcpy(thrname, OTHER);
  726.         }
  727.         else {
  728.             treshold = real(c_token);
  729.             c_token++;
  730.             if (END_OF_COMMAND)
  731.                 strcpy(thrname, OTHER);
  732.             else if (!isstring(c_token))
  733.                 int_error("name in quotes expected", c_token);
  734.             else {
  735.                 quote_str(thrname, c_token);
  736.                 c_token++;
  737.             }
  738.         }
  739.     }
  740.     else
  741.         int_error("valid options: '[counter_]clockwise',\n\
  742. 'explode', 'radius', 'samples', 'threshold'",c_token);
  743. }
  744.  
  745. get_HL()
  746. {
  747.     if (END_OF_COMMAND) return(HL_NON);
  748.     else if (almost_equals(c_token,"n$one")) {
  749.         c_token++;
  750.         return(HL_NON);
  751.     }
  752.     else if (almost_equals(c_token,"mi$nim")) {
  753.         c_token++;
  754.         return(HL_MIN);
  755.     }
  756.     else if (almost_equals(c_token,"ma$xim")) {
  757.         c_token++;
  758.         return(HL_MAX);
  759.     }
  760.     else if (isnumber(c_token)) {
  761.         return((int) real(c_token++));
  762.     }
  763.     else
  764.         int_error("'maximum', 'minimum', 'none' or number expected",c_token);
  765.     /*NOTREACHED*/
  766. }
  767.  
  768. show_stuff()
  769. {
  770.     if (almost_equals(++c_token,"sc$ale")) {
  771.         (void) putc('\n',stderr);
  772.         show_autoscale();
  773.         c_token++;
  774.     }
  775.     else if (almost_equals(c_token,"au$tolabeling")) {
  776.         (void) putc('\n',stderr);
  777.         show_label();
  778.         c_token++;
  779.     }
  780.     else if (almost_equals(c_token,"lo$gscale")) {
  781.         (void) putc('\n',stderr);
  782.         show_logscale();
  783.         c_token++;
  784.     }
  785.     else if (almost_equals(c_token,"la$bel")) {
  786.         (void) putc('\n',stderr);
  787.         c_token++;
  788.         if (END_OF_COMMAND)
  789.             show_labels(0, stderr, FALSE);
  790.         else {
  791.             show_labels((int)real(c_token), stderr, FALSE);
  792.             c_token++;
  793.         }
  794.     }
  795.     else if (almost_equals(c_token,"li$ne") || almost_equals(c_token,"ar$row")) {
  796.         (void) putc('\n',stderr);
  797.         c_token++;
  798.         if (END_OF_COMMAND)
  799.             show_arrow(0, stderr, FALSE);
  800.         else {
  801.             show_arrow((int)real(c_token), stderr, FALSE);
  802.             c_token++;
  803.         }
  804.     }    
  805.     else if (almost_equals(c_token,"bas$e")) {
  806.         (void) putc('\n',stderr);
  807.         show_base();
  808.         c_token++;
  809.     }
  810.     else if (almost_equals(c_token,"fr$ame")) {
  811.         (void) putc('\n',stderr);
  812.         show_border();
  813.         c_token++;
  814.     }
  815.     else if (almost_equals(c_token,"for$mat")) {
  816.         (void) putc('\n',stderr);
  817.         show_format();
  818.         c_token++;
  819.     }
  820.     else if (almost_equals(c_token,"fon$t")) {
  821.         (void) putc('\n',stderr);
  822.         show_font();
  823.         c_token++;
  824.     }    
  825.     else if (almost_equals(c_token,"cl$ockwise")) {
  826.         (void) putc('\n',stderr);
  827.         show_clock(TRUE);
  828.         show_clock(FALSE);
  829.         c_token++;
  830.     }
  831.     else if (almost_equals(c_token,"cu$stomized")) {
  832.         (void) putc('\n',stderr);
  833.         show_custom();
  834.         c_token++;
  835.     }
  836.     else if (almost_equals(c_token,"ex$plode")) {
  837.         (void) putc('\n',stderr);
  838.         show_explode();
  839.         c_token++;
  840.     }
  841.     else if (almost_equals(c_token,"gr$avitation")) {
  842.         (void) putc('\n',stderr);
  843.         show_gravity();
  844.         c_token++;
  845.     }
  846.     else if (almost_equals(c_token,"h$ighlight")) {
  847.         (void) putc('\n',stderr);
  848.         show_HLset();
  849.         c_token++;
  850.     }
  851.     else if (almost_equals(c_token,"i$nput")) {
  852.         (void) putc('\n',stderr);
  853.         show_input();
  854.         c_token++;
  855.     }
  856.     else if (almost_equals(c_token,"of$fsets")) {
  857.         (void) putc('\n',stderr);
  858.         show_offsets();
  859.         c_token++;
  860.     }
  861.     else if (almost_equals(c_token,"o$utput")) {
  862.         (void) putc('\n',stderr);
  863.         show_output();
  864.         c_token++;
  865.     }
  866.     else if (almost_equals(c_token,"sa$mples")) {
  867.         (void) putc('\n',stderr);
  868.         show_samples();
  869.         c_token++;
  870.     }
  871.     else if (almost_equals(c_token,"st$yle")) {
  872.         (void) putc('\n',stderr);
  873.         c_token++;
  874.         show_style();
  875.     }
  876.     else if (almost_equals(c_token,"si$ze")) {
  877.         (void) putc('\n',stderr);
  878.         c_token++;
  879.         show_size();
  880.     }
  881.     else if (almost_equals(c_token,"te$rminal")) {
  882.         (void) putc('\n',stderr);
  883.         show_term();
  884.         c_token++;
  885.     }
  886.     else if (almost_equals(c_token,"ti$tle")) {
  887.         (void) putc('\n',stderr);
  888.         show_title();
  889.         c_token++;
  890.     }
  891.     else if (almost_equals(c_token,"th$reshold")) {
  892.         (void) putc('\n',stderr);
  893.         show_tresh();
  894.         c_token++;
  895.     }
  896.     else if (almost_equals(c_token,"tr$uncate")) {
  897.         (void) putc('\n',stderr);
  898.         show_trunc();
  899.         c_token++;
  900.     }    
  901.     else if (almost_equals(c_token,"w$idth")) {
  902.         (void) putc('\n',stderr);
  903.         show_width();
  904.         c_token++;
  905.     }
  906.     else if (almost_equals(c_token,"ve$rsion")) {
  907.         show_version();
  908.         c_token++;
  909.     }
  910.     else if (almost_equals(c_token,"rad$ius")) {
  911.         (void) putc('\n',stderr);
  912.         show_radius();
  913.         c_token++;
  914.     }
  915.     else if (almost_equals(c_token,"r$ange")) {
  916.         (void) putc('\n',stderr);
  917.         show_range();
  918.         c_token++;
  919.     }
  920.     else if (almost_equals(c_token,"z$ero") ||
  921.              almost_equals(c_token,"eps$ilon")) {
  922.         (void) putc('\n',stderr);
  923.         show_zero();
  924.         c_token++;
  925.     }
  926.     else if (almost_equals(c_token,"g$eneral")) {    /* no more !!! */
  927.         c_token++;
  928.         show_version();
  929.         show_input();
  930.         show_custom();
  931.         show_range();
  932.         show_label();
  933.         show_trunc();
  934.         show_output();
  935.         show_term();
  936.         show_size();
  937.         show_offsets();
  938.         show_border();
  939.         show_font();
  940.         show_title();
  941.         show_labels(0, stderr, FALSE);
  942.         show_arrow(0, stderr, FALSE);
  943.         show_logscale();
  944.         show_format();
  945.         show_zero();
  946.         show_HLset();
  947.         show_style();
  948.     }
  949.     else if (almost_equals(c_token,"bar$charts")) {
  950.         c_token++;
  951.         show_version();
  952.         show_style();
  953.         fprintf(stderr,"\n\tsettings for barcharts (any bar style):\n\n");
  954.         show_base();
  955.         show_width();
  956.         show_autoscale();
  957.         show_gravity();
  958.         show_clock(FALSE);
  959.     }
  960.     else if (almost_equals(c_token,"pie$charts")) {
  961.         c_token++;
  962.         show_version();
  963.         show_style();
  964.         fprintf(stderr,"\n\tsettings for piecharts:\n\n");
  965.         show_clock(TRUE);
  966.         show_explode();
  967.         show_radius();
  968.         show_tresh();
  969.         show_samples();
  970.     }        
  971.     else if (almost_equals(c_token,"a$ll")) {
  972.         c_token++;
  973.         show_version();
  974.         show_input();
  975.         show_custom();
  976.         show_range();
  977.         show_label();
  978.         show_trunc();
  979.         show_output();
  980.         show_term();
  981.         show_size();
  982.         show_offsets();
  983.         show_border();
  984.         show_font();
  985.         show_title();
  986.         show_labels(0, stderr, FALSE);
  987.         show_arrow(0, stderr, FALSE);
  988.         show_logscale();
  989.         show_format();
  990.         show_zero();
  991.         show_HLset();
  992.         show_style();
  993.         show_base();
  994.         show_width();
  995.         show_autoscale();
  996.         show_gravity();
  997.         show_clock(FALSE);    /* bars */
  998.         show_clock(TRUE);    /* pies */
  999.         show_explode();
  1000.         show_radius();
  1001.         show_tresh();
  1002.         show_samples();
  1003.     }
  1004.     else
  1005.         int_error(
  1006.     "valid show options:  'all', 'scale', 'base', 'font'\n\
  1007. 'customized', 'explode', 'gravitation', 'highlight',\n\
  1008. 'input', 'logscale', 'offsets', 'output', 'label',\n\
  1009. 'samples', 'style', 'terminal', 'version', 'range',\n\
  1010. 'radius', 'clockwise', 'width', 'zero/epsilon', 'frame',\n\
  1011. 'size', 'general', 'barcharts', 'piecharts', 'format',\n\
  1012. 'threshold', 'truncate', 'line', 'arrow', 'autolabeling'",
  1013. c_token);
  1014.     screen_ok = FALSE;
  1015.     (void) putc('\n',stderr);
  1016. }
  1017.  
  1018.  
  1019. load_offsets (a, b, c, d)
  1020. double *a, *b, *c, *d;
  1021. {
  1022.     *a = real (c_token);  /* loff value */
  1023.     if (*a >= 100.0 && d)
  1024.         int_error("value <0,100) expected",c_token);
  1025.     c_token++;
  1026.     if (equals(c_token,","))
  1027.         c_token++;
  1028.     if (END_OF_COMMAND) 
  1029.         return;
  1030.  
  1031.     *b = real (c_token);  /* roff value */
  1032.     if (*b >= 100.0 && d)
  1033.         int_error("value <0,100) expected",c_token);        
  1034.     c_token++;
  1035.     if (equals(c_token,","))
  1036.         c_token++;
  1037.     if (END_OF_COMMAND) 
  1038.         return;
  1039.  
  1040.     *c = real (c_token);  /* toff value */
  1041.     if (*c >= 100.0 && d)
  1042.         int_error("value <0,100) expected",c_token);
  1043.     c_token++;
  1044.  
  1045.     if (!d) return;
  1046.     if (equals(c_token,","))
  1047.         c_token++;
  1048.     if (END_OF_COMMAND) 
  1049.         return;
  1050.  
  1051.     *d = real (c_token);  /* boff value */
  1052.     if (*d >= 100.0)
  1053.         int_error("value <0,100) expected",c_token);
  1054.     c_token++;
  1055. }
  1056.  
  1057.  
  1058. load_range(a,b)
  1059. int *a, *b;
  1060. {
  1061.     if (equals(c_token,"]"))
  1062.         return;  /* no change */
  1063.     if (END_OF_COMMAND) {
  1064.         int_error("starting range value or ':' expected",c_token);
  1065.     } else if (!equals(c_token,"to") && !equals(c_token,":"))  {
  1066.         *a = (int)real(c_token);
  1067.         c_token++;
  1068.     }
  1069.     else *a = 0;    /* from the very begining */
  1070.     if (!equals(c_token,"to") && !equals(c_token,":"))
  1071.         int_error("':' expected",c_token);
  1072.     c_token++;
  1073.     if (!equals(c_token,"]")) {
  1074.         *b = (int)real(c_token);
  1075.         c_token++;
  1076.     }
  1077.     else *b = -1;    /* to infinity */
  1078. }
  1079.  
  1080.  
  1081. plotrequest(xplot)
  1082. BOOLEAN xplot;
  1083. {
  1084.     
  1085.     if (!term)                    /* unknown */
  1086.         int_error("use 'set term' to set terminal type first",c_token);
  1087.  
  1088.     if (log_y && base<1.0 && data_style != PIECHART)
  1089.         int_error("base for bars out of range for logscale",NO_CARET);
  1090.  
  1091.     if (equals(c_token,"[")) {
  1092.         c_token++;
  1093.         load_range(&xmin,&xmax);
  1094.         if (!equals(c_token,"]"))
  1095.             int_error("']' expected",c_token);
  1096.         c_token++;
  1097.         if (xmax != -1 && xmax < xmin)
  1098.             int_error("given range is empty",NO_CARET);
  1099.     }
  1100.  
  1101.     eval_plots(xplot);
  1102. }
  1103.  
  1104. int missing(s)
  1105. char *s;
  1106. /* check if s represents a missing value (spaces and dot) */
  1107. {
  1108.     char *p = s + strlen(s) - 1;
  1109.     if (!s || !*s)
  1110.         return(1);
  1111.     while (isspace(*s)) s++;
  1112.     if (s == p && *s == '.')
  1113.         return(1);
  1114.     else
  1115.         return(0);
  1116. }
  1117.  
  1118. get_data(this_plot,this_style)
  1119. struct dfile *this_plot;
  1120. enum INP_STYLE this_style;
  1121. {
  1122.     static char data_file[MAX_LINE_LEN+1], line[MAX_LINE_LEN+1];
  1123.     register int i, l_num, ob_num, scanval;
  1124.     register FILE *fp;
  1125.     double x;
  1126.     struct chunk *chn;
  1127.     char *labpt;
  1128.     int chsiz = CH_INIT_SIZE;
  1129.     int lablen, aux;
  1130.  
  1131.     quote_str(data_file, c_token);
  1132.     m_quote_capture(&(this_plot->fname), c_token, c_token);
  1133.  
  1134.     chn = (struct chunk *) alloc((unsigned)sizeof(struct chunk), data_file);
  1135.     chn->next = NULL;    /* in case of further errors */
  1136.     chn->dval = NULL;
  1137.     chn->vlbl = (char **) NULL;
  1138.     this_plot->data = chn;
  1139.     this_plot->chunks = 1;
  1140.     if (xmin != -1 && xmax != -1)         /* known number of data */
  1141.         chsiz = xmax - xmin + 1;
  1142.     chn->dval = (vreal *) alloc((unsigned)chsiz*sizeof(vreal), data_file);
  1143.     chn->used = 0;
  1144.     if (this_style != CUSTOMD || label_plac.from != -1) {    /* labels expected */
  1145.         chn->vlbl = (char **) alloc((unsigned)chsiz*sizeof(char *), data_file);
  1146.         for (i=0; i<chsiz; i++)
  1147.             chn->vlbl[i] = (char *) NULL;
  1148.     }
  1149.     this_plot->d_min =  VERYLARGE;
  1150.     this_plot->d_max = -VERYLARGE;
  1151.     this_plot->points = 0;
  1152.     this_plot->makeHL = HL_NON;
  1153.     this_plot->labels = TRUE;        /* label autogenerating may be possible */
  1154.  
  1155.     if (!(fp = fopen(data_file, "r")))
  1156.         os_error("can't open data file", c_token);
  1157.         
  1158.     l_num = 0;
  1159.     ob_num = -1;        /* will be incremented before any operation */
  1160.     i = -1;
  1161.  
  1162.     while (fgets(line, MAX_LINE_LEN, fp)) {                            /* REWRITE ALL !!! */
  1163.         l_num++;
  1164.         if (is_comment(line[0]) && this_style != CUSTOMD)    /* label can be on any position, incl. 1st column */
  1165.             continue;        /* ignore comments */
  1166.  
  1167.         i++;
  1168.         if (i<xmin) continue;    /* still out of range */
  1169.         if (xmax != -1 && i>xmax) break;    /* don't even read the rest of file */
  1170.  
  1171.         line[strlen(line)-1] = '\0';    /* get rid of '\n' */
  1172.         ob_num++;
  1173.         if (ob_num==chsiz) {    /* open new chunk */
  1174.             chn->next = (struct chunk *) alloc((unsigned)sizeof(struct chunk), data_file);
  1175.             chn = chn->next;
  1176.             chn->next = NULL;    /* in case of further errors */
  1177.             chn->dval = NULL;
  1178.             chn->vlbl = (char **) NULL;
  1179.             this_plot->chunks++;
  1180.             this_plot->points += chsiz;        /* chunkful of points */
  1181.             chsiz *= 2;            /* probably the optimal allocation step */
  1182.             chn->dval = (vreal *) alloc((unsigned)chsiz*sizeof(vreal), (char *)NULL);
  1183.             if (!chn->dval)
  1184.                 (void) fclose(fp),
  1185.                 int_error("out of memory",c_token);
  1186.             chn->used = 0;        /* this one */
  1187.             if (this_style != CUSTOMD || label_plac.from != -1) {    /* labels expected */
  1188.                 chn->vlbl = (char **) alloc((unsigned)chsiz*sizeof(char *), (char *)NULL);
  1189.                 if (!chn->vlbl)
  1190.                     (void) fclose(fp),
  1191.                     int_error("out of memory",c_token++);
  1192.                 else {
  1193.                     int ii;
  1194.                     for (ii=0; ii<chsiz; ii++)
  1195.                         chn->vlbl[ii] = (char *) NULL;
  1196.                 }
  1197.             }
  1198.             ob_num = 0;
  1199.         }
  1200.  
  1201.         if (!*line && this_style != CUSTOMD) {     /* empty data == missing value. not in SAS */
  1202.             chn->dval[ob_num] = VERYLARGE;    
  1203.             if (chn->vlbl)
  1204.                 chn->vlbl[ob_num] = (char *) NULL;
  1205.             chn->used++;
  1206.             continue;
  1207.         }
  1208.  
  1209.         /* so here we go. now consider input format */
  1210.         switch (this_style) {
  1211.             case PRIVATE:
  1212.                 scanval = sscanf(line,"%lf",&x);
  1213.                 if (scanval == 1) {
  1214.                     for (labpt = line; *labpt && isspace(*labpt); labpt++) ;
  1215.                     while (*labpt && !isspace(*labpt)) labpt++;
  1216.                     lablen = strlen(labpt);        /* initialy */
  1217.                 }
  1218.                 break;
  1219.             case GNUPLOT:
  1220.                 scanval = sscanf(line,"%*lf %lf",&x);
  1221.                 if (scanval == 1) {
  1222.                     for (aux=0; isspace(line[aux]); aux++);
  1223.                     labpt = line + aux;
  1224.                     for (lablen=0; !isspace(line[aux++]); lablen++) ;
  1225.                 }
  1226.                 else labpt=NULL, scanval = sscanf(line,"%lf",&x);
  1227.                 break;
  1228.             case CUSTOMD:
  1229.                 if (strlen(line) < data_place.from) {
  1230.                     scanval = 0;        /* generate error */
  1231.                     break;
  1232.                 }
  1233.                 labpt = line + data_place.from;
  1234.                 if (data_place.upto == -1 || data_place.upto >= strlen(line))
  1235.                     if (missing(labpt))
  1236.                         x = VERYLARGE;
  1237.                     else
  1238.                         scanval = sscanf(labpt,"%lf",&x);
  1239.                 else {
  1240.                     aux = line[data_place.upto];
  1241.                     line[data_place.upto] = '\0';
  1242.                     if (missing(labpt))
  1243.                         x = VERYLARGE;
  1244.                     else
  1245.                         scanval = sscanf(labpt,"%lf",&x);
  1246.                     line[data_place.upto] = aux;
  1247.                 }
  1248.                 if (x == VERYLARGE) {         /* missing value detected, or unplottable anyway */
  1249.                     chn->dval[ob_num] = VERYLARGE;
  1250.                     if (chn->vlbl)
  1251.                         chn->vlbl[ob_num] = (char *) NULL;
  1252.                     chn->used++;
  1253.                     continue;
  1254.                 }
  1255.                 if (label_plac.from >= strlen(line) || label_plac.from == -1) 
  1256.                     labpt = NULL;
  1257.                 else {
  1258.                     labpt = line + label_plac.from;
  1259.                     if (label_plac.upto == -1 || label_plac.upto >= strlen(line))
  1260.                         lablen = strlen(labpt);
  1261.                     else
  1262.                         lablen = label_plac.upto - label_plac.from - 1;
  1263.                 }
  1264.                 break;
  1265.             }
  1266.  
  1267.         if (scanval != 1) {        /* can be also EOF for empty line */
  1268.             (void) sprintf(line, "bad data on line %d", l_num);
  1269.             (void) fclose(fp);
  1270.             int_error(line,c_token);
  1271.         }
  1272.  
  1273.         if (x<0.0 && data_style == PIECHART ||
  1274.             x<1.0 && data_style != PIECHART && log_y) {
  1275.             (void) fclose(fp);
  1276.             (void) sprintf(line,"unplotable data on line %d",l_num);
  1277.             int_error(line,c_token);
  1278.         }
  1279.  
  1280.         if (log_y) x = log10(x);
  1281.         
  1282.         chn->dval[ob_num] = (vreal) x;
  1283.         if (x<this_plot->d_min) this_plot->d_min = (vreal) x;
  1284.         if (x>this_plot->d_max) this_plot->d_max = (vreal) x;  /* without 'else', I know */
  1285.         
  1286.         if (labpt && *labpt && lablen && strunc!=0) {    /* copy existing label -- ignore if empty */
  1287.             char *q;
  1288.             /* remove meaningless spaces */
  1289.             while (isspace(*labpt)) labpt++, lablen--;
  1290.             while (isspace(labpt[lablen])) lablen--;
  1291.             if (strunc>0 && strunc<lablen)
  1292.                 lablen = strunc;
  1293.             if (!lablen)    /* truncated to zero */
  1294.                 chn->vlbl[ob_num] = (char *) NULL;
  1295.             else {
  1296.                 if (!(q = alloc((unsigned) lablen+1, (char *)NULL))) {
  1297.                     (void) fclose(fp);
  1298.                     int_error("out of memory",c_token);
  1299.                 }
  1300.                 (void) strncpy(q,labpt,lablen);
  1301.                 q[lablen] = '\0';
  1302.                 chn->vlbl[ob_num] = q;
  1303.                 this_plot->labels = FALSE;    /* cannot autogenerate labels if some exist */
  1304.             }
  1305.         }
  1306.         else
  1307.             chn->vlbl[ob_num] = (char *) NULL;
  1308.  
  1309.         chn->used++;
  1310.     } /* while */
  1311.  
  1312.     (void) fclose(fp);
  1313.     if (i<xmin)
  1314.         int_error("too few data",c_token);
  1315.  
  1316.     this_plot->points += chn->used;
  1317.  
  1318. }
  1319.  
  1320. eval_plots(xplot)
  1321. BOOLEAN xplot;
  1322. {
  1323.     struct dfile *dp = &data_head, *tail;
  1324.     enum INP_STYLE in_st;
  1325.  
  1326.     data_head.d_min = VERYLARGE; data_head.d_max = -VERYLARGE;
  1327.     data_head.points = data_head.chunks = 0;
  1328.     if (data_head.data) free((char *)data_head.data);
  1329.     data_head.data = NULL;
  1330.     destroy(data_head.dnxt);
  1331.     data_head.dnxt = (struct dfile *) NULL;
  1332.     data_head.makeHL = HLitem;
  1333.     data_head.labels = auto_label;
  1334.  
  1335.     while (TRUE) {
  1336.         if (END_OF_COMMAND)
  1337.             int_error("data file to plot expected",c_token);
  1338.         if (equals(c_token,"(")) {
  1339.             c_token++;
  1340.             in_st = get_input();
  1341.             if (END_OF_COMMAND || !equals(c_token,")"))
  1342.                 int_error("expected ')'",c_token);
  1343.             c_token++;
  1344.         }
  1345.         else
  1346.             in_st = inp_style;
  1347.         if (in_st == CUSTOMD && data_place.from == -1)
  1348.             int_error("Customized input format not defined. Use 'set customized'",NO_CARET);
  1349.         
  1350.         if (END_OF_COMMAND || !isstring(c_token)) 
  1351.             int_error("data file to plot expected",c_token);
  1352.         tail = (struct dfile *) alloc((unsigned int) sizeof(struct dfile), "data");
  1353.         tail->fname = NULL;
  1354.         tail->data  = NULL;
  1355.         tail->dnxt  = NULL;
  1356.         dp->dnxt    = tail;    /* to free all memory on error */
  1357.  
  1358.         get_data(tail,in_st);
  1359.  
  1360.         c_token++;
  1361.         dp             = tail;
  1362.         data_head.chunks++;  /* here we count overall number of files */
  1363.         if (data_style != ABARS && data_style != PIECHART || xplot)    /* if (ABARS || PIECHART => xplot) */
  1364.             data_head.labels = data_head.labels && dp->labels;    /* is making labels sensible or not ? */
  1365.         /* else this serves different purpose */
  1366.         if (data_head.points < dp->points)
  1367.             data_head.points = dp->points;  /* ... and maximal number of points */
  1368.         if (data_head.d_min > dp->d_min)
  1369.             data_head.d_min = dp->d_min;    /* minimum ... */
  1370.         if (data_head.d_max < dp->d_max)
  1371.             data_head.d_max = dp->d_max;    /* and maximum */
  1372.  
  1373.         if (almost_equals(c_token,"a$s")) {
  1374.             c_token++;
  1375.             if (END_OF_COMMAND || !isstring(c_token))
  1376.                 int_error("name in quotes expected", c_token);
  1377.             else {
  1378.                 m_quote_capture(&(dp->fname), c_token, c_token);
  1379.                 c_token++;
  1380.             }
  1381.         }
  1382.         
  1383.         if (almost_equals(c_token,"h$ighlighting")) {
  1384.             c_token++;
  1385.             dp->makeHL = get_HL();
  1386.         }
  1387.  
  1388.         if (END_OF_COMMAND)
  1389.             break;
  1390.         else if (equals(c_token,","))
  1391.             c_token++;
  1392.         else
  1393.             int_error("expected ','",c_token);
  1394.     }
  1395.  
  1396.     if (data_head.d_min == VERYLARGE || data_head.d_max == -VERYLARGE)
  1397.         int_error("all points undefined, nothing to draw",NO_CARET);
  1398.  
  1399.     if (data_head.chunks > 1) {        /* reserve space for xpointers structure */
  1400.         /* do it here, to avoid memory management in graphics.c */
  1401.         data_head.data = (struct chunk *) alloc((unsigned)data_head.chunks*sizeof(struct xptr), "data");
  1402.     }
  1403.  
  1404.     capture(replot_line,plot_token,c_token);
  1405.     do_plot(xplot,data_style,xmin<=0?0:xmin);
  1406. }
  1407.  
  1408. done(status)
  1409. int status;
  1410. {
  1411.     if (term && term_init)
  1412.         (*term_tbl[term].reset)();
  1413. #ifdef VMS
  1414.     vms_reset();
  1415. #endif
  1416.     exit(status);
  1417. }
  1418.  
  1419. #ifdef MSDOS
  1420. #ifndef __TURBOC__  /* Turbo C already has sleep() */
  1421. #ifndef __ZTC__     /* ZTC already has usleep() */
  1422. /* kludge to provide sleep() for msc 5.1 */
  1423. void sleep(delay)
  1424. unsigned int delay;
  1425. {
  1426. unsigned long time_is_up;
  1427.     time_is_up = time(NULL) + (unsigned long) delay;
  1428.     while (time(NULL)<time_is_up)
  1429.         /* wait */ ;
  1430. }
  1431. #endif /* not ZTC */
  1432. #endif /* not TURBOC */
  1433. #endif /* MSDOS */
  1434.  
  1435.  
  1436. /* Support for input, shell, and help for various systems */
  1437.  
  1438. #ifdef vms
  1439.  
  1440. #include <descrip.h>
  1441. #include <rmsdef.h>
  1442. #include <errno.h>
  1443.  
  1444. extern lib$get_input(), lib$put_output();
  1445.  
  1446. int vms_len;
  1447.  
  1448. unsigned int status[2] = {1, 0};
  1449.  
  1450. static char help[MAX_LINE_LEN+1] = "fchart";
  1451.  
  1452. $DESCRIPTOR(prompt_desc,PROMPT);
  1453. $DESCRIPTOR(line_desc,input_line);
  1454.  
  1455. $DESCRIPTOR(help_desc,help);
  1456. $DESCRIPTOR(helpfile_desc,"FCHART$HELP");
  1457.  
  1458. read_line(prompt)
  1459. char *prompt;
  1460. {
  1461.     int more, start=0;
  1462.     char exp_prompt = EXP_PROMPT;
  1463.     prompt_desc.dsc$w_length = strlen (prompt);
  1464.     prompt_desc.dsc$a_pointer = prompt;
  1465.     do {
  1466.         line_desc.dsc$w_length = MAX_LINE_LEN - start;
  1467.         line_desc.dsc$a_pointer = &input_line[start];
  1468.         switch(status[1] = lib$get_input(&line_desc, &prompt_desc, &vms_len)){
  1469.             case RMS$_EOF:
  1470.                 done(IO_SUCCESS);    /* ^Z isn't really an error */
  1471.                 break;
  1472.             case RMS$_TNS:            /* didn't press return in time */
  1473.                 vms_len--;        /* skip the last character */
  1474.                 break;            /* and parse anyway */
  1475.             case RMS$_BES:            /* Bad Escape Sequence */
  1476.             case RMS$_PES:            /* Partial Escape Sequence */
  1477.                 sys$putmsg(status);
  1478.                 vms_len = 0;        /* ignore the line */
  1479.                 break;
  1480.             case SS$_NORMAL:
  1481.                 break;            /* everything's fine */
  1482.             default:
  1483.                 done(status[1]);    /* give the error message */
  1484.         }
  1485.         start += vms_len;
  1486.         input_line[start] = '\0';
  1487.         if (input_line[start-1] == '\\') {
  1488.           /* Allow for a continuation line. */
  1489.           prompt_desc.dsc$w_length = strlen (exp_prompt);
  1490.           prompt_desc.dsc$a_pointer = exp_prompt;
  1491.           more = 1;
  1492.           --start;
  1493.         }
  1494.         else {
  1495.           line_desc.dsc$w_length = strlen(input_line);
  1496.           line_desc.dsc$a_pointer = input_line;
  1497.           more = 0;
  1498.         }
  1499.     } while (more);        
  1500. }
  1501.  
  1502.  
  1503. do_help()
  1504. {
  1505.     help_desc.dsc$w_length = strlen(help);
  1506.     if ((vaxc$errno = lbr$output_help(lib$put_output,0,&help_desc,
  1507.         &helpfile_desc,0,lib$get_input)) != SS$_NORMAL)
  1508.             os_error("can't open FCHART$HELP");
  1509. }
  1510.  
  1511.  
  1512. do_shell()
  1513. {
  1514.     if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
  1515.         os_error("spawn error",NO_CARET);
  1516.     }
  1517. }
  1518.  
  1519.  
  1520. do_system()
  1521. {
  1522.     input_line[0] = ' ';    /* an embarrassment, but... */
  1523.  
  1524.     if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
  1525.         os_error("spawn error",NO_CARET);
  1526.  
  1527.     (void) putc('\n',stderr);
  1528. }
  1529.  
  1530. #else /* vms */
  1531.  
  1532. /* do_help: (not VMS, although it would work)
  1533.  * Give help to the user.
  1534.  * It parses the command line into helpbuf and supplies help for that
  1535.  * string. Then, if there are subtopics available for that key,
  1536.  * it prompts the user with this string. If more input is
  1537.  * given, do_help is called recursively, with the argument the index of
  1538.  * null character in the string. Thus a more specific help can be
  1539.  * supplied. This can be done repeatedly.
  1540.  * If null input is given, the function returns, effecting a
  1541.  * backward climb up the tree.
  1542.  * David Kotz (dfk@cs.duke.edu) 10/89
  1543.  */
  1544. do_help()
  1545. {
  1546.     static char helpbuf[MAX_LINE_LEN] = "";
  1547.     static char prompt[MAX_LINE_LEN] = "";
  1548.     int base;               /* index of first char AFTER help string */
  1549.     int len;                /* length of current help string */
  1550.     BOOLEAN more_help;
  1551.     BOOLEAN only;           /* TRUE if only printing subtopics */
  1552.     int subtopics;          /* 0 if no subtopics for this topic */
  1553.     int start;              /* starting token of help string */
  1554.     char *help_ptr;         /* name of help file */
  1555.     
  1556.     if ( (help_ptr = getenv("FCHARTHELP")) == (char *)NULL )
  1557.         /* if can't find environment variable then just use HELPFILE */
  1558.         help_ptr = HELPFILE;
  1559.     
  1560.     len = base = strlen(helpbuf);
  1561.     
  1562.     /* find the end of the help command */
  1563.     for (start = c_token; !(END_OF_COMMAND); c_token++) ;
  1564.     /* copy new help input into helpbuf */
  1565.     if (len > 0)
  1566.         helpbuf[len++] = ' ';  /* add a space */
  1567.     capture(helpbuf+len, start, c_token-1);
  1568.     squash_spaces(helpbuf+base); /* only bother with new stuff */
  1569.     lower_case(helpbuf+base); /* only bother with new stuff */
  1570.     len = strlen(helpbuf);
  1571.     
  1572.     /* now, a lone ? will print subtopics only */
  1573.     if (strcmp(helpbuf + (base ? base+1 : 0), "?") == 0) {
  1574.         /* subtopics only */
  1575.         subtopics = 1;
  1576.         only = TRUE;
  1577.         helpbuf[base] = '\0';    /* cut off question mark */
  1578.     } else {
  1579.         /* normal help request */
  1580.         subtopics = 0;
  1581.         only = FALSE;
  1582.     }
  1583.     
  1584.     switch ( help(helpbuf, help_ptr, &subtopics)) {
  1585.         case H_FOUND: {
  1586.             /* already printed the help info */
  1587.             /* subtopics now is true if there were any subtopics */
  1588.             screen_ok = FALSE;
  1589.             
  1590.             do {
  1591.                 if (subtopics && !only) {
  1592.                     /* prompt for subtopic with current help string */
  1593.                     if (len > 0)
  1594.                         (void) sprintf(prompt, "Subtopic of %s: ", helpbuf);
  1595.                     else
  1596.                         (void) strcpy(prompt, "Help topic: ");
  1597.                     read_line(prompt);
  1598.                     num_tokens = scanner(input_line);
  1599.                     c_token = 0;
  1600.                     more_help = !(END_OF_COMMAND);
  1601.                     if (more_help)
  1602.                         /* base for next level is all of current helpbuf */
  1603.                         do_help();
  1604.                 } else
  1605.                     more_help = FALSE;
  1606.             } while(more_help);
  1607.             
  1608.             break;
  1609.         }
  1610.         case H_NOTFOUND: {
  1611.             printf("Sorry, no help for '%s'\n", helpbuf);
  1612.             break;
  1613.         }
  1614.         case H_ERROR: {
  1615.             perror(help_ptr);
  1616.             break;
  1617.         }
  1618.         default: {       /* defensive programming */
  1619.             int_error("Impossible case in switch\n", NO_CARET);
  1620.             /* NOTREACHED */
  1621.         }
  1622.     }
  1623.     
  1624.     helpbuf[base] = '\0';   /* cut it off where we started */
  1625. }
  1626.  
  1627. do_system()
  1628. {
  1629.     if (system(input_line + 1))
  1630.         os_error("system() failed",NO_CARET);
  1631. }
  1632.  
  1633. #ifdef MSDOS
  1634.  
  1635. read_line(prompt)
  1636. char *prompt;
  1637. {
  1638.     int last, start = 0;
  1639.     BOOLEAN more;
  1640.  
  1641. #ifndef __ZTC__
  1642.     if (interactive) { /* if interactive use console IO so CED will work */
  1643.         cputs(prompt);
  1644.         do {
  1645.             input_line[start] = MAX_LINE_LEN - start - 1;
  1646.             cgets(&(input_line[start]));
  1647.             (void) putc('\n',stderr);
  1648.             if (input_line[start+2] == 26) {
  1649.                 /* end-of-file */
  1650.                 (void) putc('\n',stderr);
  1651.                 input_line[start] = '\0';
  1652.                 if (start > 0)    /* don't quit yet - process what we have */
  1653.                     more = FALSE;
  1654.                 else {
  1655.                     (void) putc('\n',stderr);
  1656.                     done(IO_SUCCESS);
  1657.                     /* NOTREACHED */
  1658.                 }
  1659.             } else {
  1660.                 /* normal line input */
  1661.                 register i = start;
  1662.                 while ( (input_line[i] = input_line[i+2]) != (char)NULL )
  1663.                     i++;        /* yuck!  move everything down two characters */
  1664.                 
  1665.                 last = strlen(input_line) - 1;
  1666.                 if (last + 1 >= MAX_LINE_LEN)
  1667.                     int_error("Input line too long",NO_CARET);
  1668.                 
  1669.                 if (input_line[last] == '\\') { /* line continuation */
  1670.                     start = last;
  1671.                     more = TRUE;
  1672.                 } else
  1673.                     more = FALSE;
  1674.             }
  1675.             if (more && isatty(fileno(stdin)))
  1676.                 cputs(EXP_PROMPT);
  1677.         } while(more);
  1678.     }
  1679.     else { /* not interactive */
  1680. #endif /* not ZTC */
  1681.         if (interactive) 
  1682.             fputs(prompt,stderr);
  1683.         do {
  1684.             /* grab some input */
  1685.             if ( fgets(&(input_line[start]), MAX_LINE_LEN - start, stdin)
  1686.                 == (char *)NULL ) {
  1687.                 /* end-of-file */
  1688.                 if (interactive)
  1689.                     (void) putc('\n',stderr);
  1690.                 input_line[start] = '\0';
  1691.                 if (start > 0)    /* don't quit yet - process what we have */
  1692.                     more = FALSE;
  1693.                 else
  1694.                     done(IO_SUCCESS); /* no return */
  1695.             } else {
  1696.                 /* normal line input */
  1697.                 last = strlen(input_line) - 1;
  1698.                 if (input_line[last] == '\n') { /* remove any newline */
  1699.                     input_line[last] = '\0';
  1700.                     /* Watch out that we don't backup beyond 0 (1-1-1) */
  1701.                     if (last > 0) --last;
  1702.                 } else if (last+1 >= MAX_LINE_LEN)
  1703.                     int_error("Input line too long",NO_CARET);
  1704.                 
  1705.                 if (input_line[last] == '\\') { /* line continuation */
  1706.                     start = last;
  1707.                     more = TRUE;
  1708.                 } else
  1709.                     more = FALSE;
  1710.             }
  1711.             if (more && interactive)
  1712.                 fputs(EXP_PROMPT, stderr);
  1713.         } while(more);
  1714. #ifndef __ZTC
  1715.     }
  1716. #endif
  1717.     
  1718. #ifdef FILIP
  1719.     input_line[0] = MAX_LINE_LEN - 1;
  1720.     cputs(PROMPT);
  1721.     cgets(input_line);            /* console input so CED will work */
  1722.     (void) putc('\n',stderr);
  1723.     if (input_line[2] == 26) {
  1724.         (void) putc('\n',stderr);        /* end-of-file */
  1725.         done(IO_SUCCESS);
  1726.     }
  1727.     
  1728.     i = 0;
  1729.     while (input_line[i] = input_line[i+2])
  1730.         i++;        /* yuck!  move everything down two characters */
  1731. #endif
  1732. }
  1733.  
  1734.  
  1735. do_shell()
  1736. {
  1737.     register char *comspec;
  1738.     if (!(comspec = getenv("COMSPEC")))
  1739.         comspec = "\command.com";
  1740.     if (spawnl(P_WAIT,comspec,NULL) == -1)
  1741.         os_error("unable to spawn shell",NO_CARET);
  1742. }
  1743.  
  1744. #else /* MSDOS */
  1745. /* plain old Unix */
  1746.  
  1747. read_line(prompt)
  1748. char *prompt;
  1749. {
  1750.     int start=0, last=0;
  1751.     BOOLEAN more;
  1752.     
  1753.     if (interactive) fputs(prompt,stderr);
  1754.     do {
  1755.         if (!fgets(&input_line[start], MAX_LINE_LEN-start, stdin)) {
  1756.             if (interactive)
  1757.                 (void) putc('\n',stderr);        /* end-of-file */
  1758.             input_line[start] = '\0';
  1759.             if (start > 0)    /* don't quit yet - process what we have */
  1760.                 more = FALSE;
  1761.             else
  1762.                 done(IO_SUCCESS); /* no return */
  1763.         }
  1764.         else {    /* normal line input */
  1765.             last = strlen(input_line)-1;
  1766.             if (input_line[last] == '\n') { /* remove any newline */
  1767.                 input_line[last] = '\0';
  1768.                 /* Watch out that we don't backup beyond 0 (1-1-1) */
  1769.                 if (last > 0) --last;
  1770.             }
  1771.             else if (last+1 >= MAX_LINE_LEN)
  1772.                 int_error("Input line too long",NO_CARET);
  1773.             
  1774.             if (input_line[last] == '\\') { /* line continuation */
  1775.                 start = last;
  1776.                 more = TRUE;
  1777.             } else
  1778.                 more = FALSE;
  1779.         }
  1780.         if (more && interactive) fputs(EXP_PROMPT,stderr);
  1781.     } while (more);
  1782. }
  1783.  
  1784. #ifdef VFORK
  1785.  
  1786. do_shell()
  1787. {
  1788. register char *shell;
  1789. register int p;
  1790. static int execstat;
  1791.     if (!(shell = getenv("SHELL")))
  1792.         shell = SHELL;
  1793.     if ((p = vfork()) == 0) {
  1794.         execstat = execl(shell,shell,NULL);
  1795.         _exit(1);
  1796.     } else if (p == -1)
  1797.         os_error("vfork failed",c_token);
  1798.     else
  1799.         while (wait(NULL) != p)
  1800.             ;
  1801.     if (execstat == -1)
  1802.         os_error("shell exec failed",c_token);
  1803.     (void) putc('\n',stderr);
  1804. }
  1805. #else /* VFORK */
  1806.  
  1807. #define EXEC "exec "
  1808. do_shell()
  1809. {
  1810. static char exec[100] = EXEC;
  1811. register char *shell;
  1812.     if (!(shell = getenv("SHELL")))
  1813.         shell = SHELL;
  1814.  
  1815.     if (system(strncpy(&exec[sizeof(EXEC)-1],shell,
  1816.         sizeof(exec)-sizeof(EXEC)-1)))
  1817.         os_error("system() failed",NO_CARET);
  1818.  
  1819.     (void) putc('\n',stderr);
  1820. }
  1821. #endif /* VFORK */
  1822. #endif /* MSDOS */
  1823. #endif /* vms */
  1824.